package com.wss.common.wechat.filter;


import com.wss.common.context.util.SystemConfig;
import com.wss.common.wechat.util.weixin.DecryptUtil;
import com.wss.common.wechat.util.weixin.TokenUtil;
import com.wss.common.wechat.util.weixin.XStreamFactory;
import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.IOException;
import java.io.StringReader;

/**
 * @author 赵飞
 * @version V1.0
 * @Title: 微信开放平台接受消息自定义拦截器
 * @Package com.wfs.common.wechat
 * @Description:
 * @date 2017/2/15
 */
//@WebFilter(filterName = "openUrlFilter", urlPatterns = "/openMsg.action")
public class OpenUrlFilter implements Filter {

	private static Logger logger = Logger.getLogger(OpenUrlFilter.class);

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		logger.info("接收三方平台信息拦截器初始化成功");
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		//微信服务器将发送GET请求到填写的URL上,这里需要判定是否为GET请求
		boolean isGet = request.getMethod().toLowerCase().equals("get");
		logger.info("获得微信请求:" + request.getMethod() + " 方式");
		logger.info("微信请求URL:" + request.getServletPath());
		//消息来源可靠性验证
		String timestamp = request.getParameter("timestamp");// 时间戳
		String nonce = request.getParameter("nonce");       // 随机数
		String encrypt_type = request.getParameter("encrypt_type");       // 加密算法 ase
		String msg_signature = request.getParameter("msg_signature");// 微信加密签名

		logger.info("timestamp=[" + timestamp + "];nonce=[" + nonce + "];encrypt_type=[" + encrypt_type + "];msg_signature=[" + msg_signature + "]");


		//Token为weixin4j.properties中配置的Token
		String token = SystemConfig.getComponentToken();
		if (isGet) {
			//1.验证消息真实性
			//成为开发者验证
			String echostr = request.getParameter("echostr");   //
			//确认此次GET请求来自微信服务器，原样返回echostr参数内容，则接入生效，成为开发者成功，否则接入失败
			if (TokenUtil.checkSignature(token, msg_signature, timestamp, nonce)) {
				response.getWriter().write(echostr);
			}
		} else {
			//确认此次GET请求来自微信服务器，原样返回echostr参数内容，则接入生效，成为开发者成功，否则接入失败
			if (!TokenUtil.checkSignature(token, msg_signature, timestamp, nonce)) {
				//消息不可靠，直接返回
				response.getWriter().write("");
				return;
			}
			//用户每次向公众号发送消息、或者产生自定义菜单点击事件时，响应URL将得到推送
			doPost(request, response);
		}
	}

	//当普通微信用户向公众账号发消息时，微信服务器将POST消息的XML数据包到开发者填写的URL上
	//用户在关注与取消关注公众号时，微信会把这个事件推送到开发者填写的URL
	//用户每次发送语音给公众号时，微信会在推送的语音消息XML数据包中，增加一个Recongnition字段
	private void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {

		String timestamp = request.getParameter("timestamp");// 时间戳
		String nonce = request.getParameter("nonce");       // 随机数
		String encrypt_type = request.getParameter("encrypt_type");       // 加密算法 ase
		String msg_signature = request.getParameter("msg_signature");// 微信加密签名

		logger.info("timestamp=[" + timestamp + "];nonce=[" + nonce + "];encrypt_type=[" + encrypt_type + "];msg_signature=[" + msg_signature + "]");

		try {
			response.setCharacterEncoding("UTF-8");
			//response.setContentType("text/xml");
			//获取POST流
			ServletInputStream in = request.getInputStream();
			logger.info("接收到微信输入流,准备处理...");
			//IMessageHandler messageHandler = HandlerFactory.getMessageHandler();
			//处理输入消息，返回结果
			//String xml = messageHandler.invoke(in);
			//返回结果
			//获取微信推送信息：
			String fromAseXML = XStreamFactory.inputStream2String(in);
			logger.info("密文XML：\n" + fromAseXML);
			String fromXML = DecryptUtil.decryptMsg(msg_signature, timestamp, nonce, fromAseXML);
			logger.info("解密XML：\n" + fromXML);

			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			StringReader sr = new StringReader(fromXML);
			InputSource is = new InputSource(sr);
			Document document = db.parse(is);

			Element root = document.getDocumentElement();

			//目前处理两处三方平台数据处理
			String infoType = root.getElementsByTagName("InfoType").item(0).getTextContent();
			switch (infoType) {
				// 1、定时推送 ticket
				case "component_verify_ticket":
					//将ticket放入redis缓存
					NodeList node = root.getElementsByTagName("ComponentVerifyTicket");
//					RedisUtil.setValue(COMPONENT_VERIFY_TICKET,node.item(0).getTextContent());
					break;
				// 2、获取微信公众号授权处理
				case "authorized":
					//获取到公众号授权的信息推送 完善授权信息
					logger.info("开始完善用户公众号授权信息！");

			}

			response.getWriter().write("success");
		} catch (Exception ex) {
			logger.error("获取微信消息解密异常。。。。", ex);
			ex.printStackTrace();
			response.getWriter().write("success");
		}
	}

	@Override
	public void destroy() {

	}
}
